package com.heima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.util.UserThreadLocalUtil;
import com.heima.search.dto.ApArticleSearchDto;
import com.heima.search.entity.ApArticleSearch;
import com.heima.search.service.IApUserSearchService;
import com.heima.search.service.IArticleSearchService;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: itheima
 * @create: 2022-01-05 10:06
 */
@Service
public class ArticleSearchServiceImpl implements IArticleSearchService {

    /**
     * 索引库名称
     */
    private static final String INDEX_NAME = "app_info_article";

    @Autowired
    private RestHighLevelClient client;

    @Autowired
    private IApUserSearchService userSearchService;


    /**
     * 根据关键字全文检索分页文章列表，根据文章发布时间进行倒序
     *
     * @param dto 入参参数
     * @return 分页文章列表
     */
    @Override
    public ResponseResult search(ApArticleSearchDto dto) {
        try {
            //0.判断入参是否合法
            if (dto == null || StringUtils.isBlank(dto.getSearchWords())) {
                return new PageResponseResult(dto.getPage(), dto.getSize(), 0L, new ArrayList<ApArticleSearch>());
            }
            //1.创建SearchRequest对象，指定查询索引库
            SearchRequest searchRequest = new SearchRequest(INDEX_NAME);

            //2.创建SearchSourceBuilder，指定查询的各种请求体参数 包含：查询方式、分页、排序、高亮、聚合
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            //2.1 设置查询方式：全文检索查询 查询文章标题字段
            sourceBuilder.query(QueryBuilders.matchQuery("title", dto.getSearchWords()).operator(Operator.AND));
            //2.2 设置分页
            Long from = (dto.getPage() - 1) * dto.getSize();
            sourceBuilder.from(from.intValue()).size(dto.getSize());

            //2.3 设置排序
            sourceBuilder.sort("publishTime", SortOrder.DESC);

            //3.将SearchSourceBuilder关联到SearchRequest对象
            searchRequest.source(sourceBuilder);

            //4.执行检索
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


            //TODO x.异步 记录用户搜索记录，将搜索记录存入MongoDB中
            //x.1 从ThreadLocal中获取用户信息
            User user = UserThreadLocalUtil.get();
            if (user != null || dto.getEquipmentId() != null) {
                //x.2 执行保存搜索历史
                userSearchService.saveSearchRecord(dto.getSearchWords(), user.getUserId(), dto.getEquipmentId());
            }

            //5.封装响应结果数据
            //5.1 获取总记录数
            long total = searchResponse.getHits().getTotalHits().value;
            //5.2 解析业务数据
            List<ApArticleSearch> list = new ArrayList<>();
            SearchHit[] hits = searchResponse.getHits().getHits();
            if (hits != null && hits.length > 0) {
                for (SearchHit hit : hits) {
                    String sourceAsString = hit.getSourceAsString();
                    ApArticleSearch apArticleSearch = JSON.parseObject(sourceAsString, ApArticleSearch.class);
                    list.add(apArticleSearch);
                }
                return new PageResponseResult(dto.getPage(), dto.getSize(), total, list);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new PageResponseResult(dto.getPage(), dto.getSize(), 0L, new ArrayList<ApArticleSearch>());
    }
}
